package com.zyl.renamepdf.util;

import com.alibaba.excel.EasyExcel;
import com.zyl.renamepdf.domain.bo.PdfContentBO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 读取pdf指定内容，写入到excel中
 */
public class PdfReaderToExcel extends PdfReader {
    private static final Logger logger = LoggerFactory.getLogger(PdfReaderToExcel.class.getSimpleName());

    /**
     * 结束标识符
     */
    private static final String END_CODE = "63 총세액합계 ";

    /**
     * 空格
     */
    private static final String BLANK = " ";

    /**
     * 导出表格的表头
     */
    private static final List<List<String>> HEAD = Arrays.asList(
            Collections.singletonList("신고일"),
            Collections.singletonList("입항일"),
            Collections.singletonList("B/L(AWB)번호"),
            Collections.singletonList("환 율"),
            Collections.singletonList("총과세가격$"),
            Collections.singletonList("총과세가격￦"),
            Collections.singletonList("관 세"),
            Collections.singletonList("개별소비세"),
            Collections.singletonList("교통에너지환경세"),
            Collections.singletonList("주 세"),
            Collections.singletonList("교 육 세"),
            Collections.singletonList("농어촌특별세"),
            Collections.singletonList("부가가치세"),
            Collections.singletonList("신고지연가산세"),
            Collections.singletonList("미신고가산세"),
            Collections.singletonList("총세액합계"),
            Collections.singletonList("物流单号")
    );

    public static void execute() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String ymd = dateFormat.format(new Date());
        File pendingFolder = new File(BASE_FILE_PATH + File.separator + ymd);
        if (!pendingFolder.exists()) {
            logger.error("基本文件目录不存在！");
            return;
        }
        if (!pendingFolder.isDirectory()) {
            logger.error("基本文件目录不是一个文件夹！");
            return;
        }
        File[] pendingFiles = pendingFolder.listFiles();
        if (pendingFiles == null) {
            logger.error("没有待读取的文件！");
            return;
        }
        List<PdfContentBO> bos = new ArrayList<>(pendingFiles.length);
        for (File pdfFile : pendingFiles) {
            if (pdfFile.isFile()) {
                // 获取文件名称
                String pdfName = pdfFile.getName();
                if (!pdfName.toLowerCase(Locale.ROOT).endsWith(".pdf")) {
                    logger.error("{} 不是pdf文件，跳过读取", pdfName);
                    continue;
                }
                // 获取pdf内容
                String content = readPdfContent(pdfFile);
                // 提取需要的信息
                PdfContentBO bo = extractContent(content);
                if (bo != null) {
                    bos.add(bo);
                }
            }
        }
        outPutToExcel(bos, ymd);
        logger.error("处理完成！");
    }

    /**
     * 数据输出到excel中
     *
     * @param bos 数据集合
     * @param ymd 输出目录所需的日期
     */
    private static void outPutToExcel(List<PdfContentBO> bos, String ymd) {
        List<List<Object>> data = new ArrayList<>(bos.size());
        for (PdfContentBO bo : bos) {
            List<Object> objects = new ArrayList<>(17);
            objects.add(bo.getDeclarationDate());
            objects.add(bo.getEntryDate());
            objects.add(bo.getBlawbNo());
            objects.add(bo.getExchangeRate());
            objects.add(bo.getTotalTaxableDollar());
            objects.add(bo.getTotalTaxableKoreanWon());
            objects.add(bo.getTariff());
            objects.add(bo.getPersonalConsumptionTax());
            objects.add(bo.getTransportationEnergyAndEnvironmentalTax());
            objects.add(bo.getAlcoholTax());
            objects.add(bo.getEducationTax());
            objects.add(bo.getSpecialTaxOnAgricultureAndFishingVillages());
            objects.add(bo.getValueAddedTax());
            objects.add(bo.getDeclarationDelayWithAdditionalTaxCalculation());
            objects.add(bo.getUndeclaredPropertyTax());
            objects.add(bo.getTotalTaxAmount());
            objects.add(bo.getWaybillNos());
            data.add(objects);
        }
        String basePath = NEW_FILE_PATH + File.separator + ymd;
        File baseFolder = new File(basePath);
        if (!baseFolder.exists()) {
            baseFolder.mkdirs();
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        String fileName = dateFormat.format(new Date()) + ".xlsx";
        // 将数据写到excel中
        EasyExcel.write(basePath + File.separator + fileName)
                .head(HEAD)
                .autoCloseStream(Boolean.TRUE)
                .sheet("sheet1")
                .doWrite(data);
    }

    /**
     * 提取需要的信息
     *
     * @param content pdf全部内容
     * @return 需要的信息
     */
    private static PdfContentBO extractContent(String content) {
        PdfContentBO bo = null;
        if (StringUtils.isNotEmpty(content)) {
            bo = new PdfContentBO();

            String[] rowContentArray = content.split("\r\n");

            int totalRowNumber = rowContentArray.length;
            // 构建读取物流单号业务对象
            ReadWaybillNoBO waybillNoBO = new ReadWaybillNoBO(false, new StringBuilder());
            // 定义第一页变量为true
            boolean firstPage = true;

            for (int i = 0; i < totalRowNumber; i++) {
                String rowContentStr = rowContentArray[i];
//                logger.error(rowContentStr);
                if (StringUtils.isEmpty(rowContentStr)) {
                    continue;
                }

                // 不是第一页
                if (!firstPage) {
                    // 后续内容仅处理 物流单号
                    processWaybillNo(rowContentStr, waybillNoBO);
                    continue;
                }

                if (rowContentStr.contains("2 신고일") || rowContentStr.contains("6 입항일") && i + 1 < totalRowNumber) {
                    // 1 신고번호 2 신고일 3 세관.과 6 입항일 7 전자인보이스 제출번호
                    String nextRowContentStr = rowContentArray[i + 1];
                    // 43900-23-503593M 2023/12/13 016-26 2023/12/05
                    if (StringUtils.isNotEmpty(nextRowContentStr)) {
                        String[] contentSection = nextRowContentStr.split(BLANK);
                        if (contentSection.length > 3) {
                            bo.setDeclarationDate(contentSection[1]);
                            bo.setEntryDate(contentSection[3]);
                        }
                    }
                    continue;
                }

                if (rowContentStr.contains("4 B/L(AWB)번호") && i + 1 < totalRowNumber) {
                    // 4 B/L(AWB)번호 5 화물관리번호 8 반입일 9 징수형태
                    String nextRowContentStr = rowContentArray[i + 1];
                    // 582446514490 23DLSC138CI-9001-1531 2023/12/08 11
                    if (StringUtils.isNotEmpty(nextRowContentStr)) {
                        String[] contentSection = nextRowContentStr.split(BLANK);
                        if (contentSection.length > 0) {
                            bo.setBlawbNo(contentSection[0]);
                        }
                    }
                    continue;
                }

                // 处理物流单号
                if (processWaybillNo(rowContentStr, waybillNoBO)) {
                    continue;
                }

                int isExist = rowContentStr.indexOf(" 56 환   율 ");
                if (isExist > -1) {
                    // 54 결제금액(인도조건-통화종류-금액-결제방법) CFR-USD-109-TT 56 환   율 1,310.3600
                    bo.setExchangeRate(rowContentStr.substring(isExist + 10));
                    continue;
                }

                if ("55 총과세가격".equals(rowContentStr) && i + 2 < totalRowNumber) {
                    // $ 109 57 운  임 0 59 가산금액 0 64 납부번호 016-11-23-01820129
                    // ￦ 143,280 58 보험료 0 60 공제금액 0 65 부가가치세과표 154,596
                    String nextRowContentStr = rowContentArray[i + 1];
                    String nextTwoRowContentStr = rowContentArray[i + 2];

                    String[] contentSection1 = nextRowContentStr.split(BLANK);
                    if (contentSection1.length > 1) {
                        bo.setTotalTaxableDollar(contentSection1[1]);
                    }
                    String[] contentSection2 = nextTwoRowContentStr.split(BLANK);
                    if (contentSection2.length > 1) {
                        bo.setTotalTaxableKoreanWon(contentSection2[1]);
                    }
                    continue;
                }

                isExist = rowContentStr.indexOf("관      세 ");
                if (isExist == 0) {
                    // 관      세 11,310 화주전화번호: 01082205393 - 사후심사결과에 따라 적용세율 변경될 수 있음. `20.7.1일부터
                    String[] contentSection = rowContentStr.substring(isExist + 9).split(BLANK);
                    if (contentSection.length > 0) {
                        bo.setTariff(contentSection[0]);
                    }
                    continue;
                }

                isExist = rowContentStr.indexOf("개별소비세 ");
                if (isExist == 0) {
                    // 개별소비세 0
                    bo.setPersonalConsumptionTax(rowContentStr.substring(isExist + 6));
                    continue;
                }

                isExist = rowContentStr.indexOf("교통에너지환경세 ");
                if (isExist == 0) {
                    // 교통에너지환경세 0
                    bo.setTransportationEnergyAndEnvironmentalTax(rowContentStr.substring(isExist + 9));
                    continue;
                }

                isExist = rowContentStr.indexOf("주      세 ");
                if (isExist == 0) {
                    // 주      세 0
                    bo.setAlcoholTax(rowContentStr.substring(isExist + 9));
                    continue;
                }

                isExist = rowContentStr.indexOf("교  육  세 ");
                if (isExist == 0) {
                    // 교  육  세 0
                    bo.setEducationTax(rowContentStr.substring(isExist + 8));
                    continue;
                }

                isExist = rowContentStr.indexOf("농어촌특별세 ");
                if (isExist == 0) {
                    // 농어촌특별세 0
                    bo.setSpecialTaxOnAgricultureAndFishingVillages(rowContentStr.substring(isExist + 7));
                    continue;
                }

                isExist = rowContentStr.indexOf("부가가치세 ");
                if (isExist == 0) {
                    // 부가가치세 0
                    bo.setValueAddedTax(rowContentStr.substring(isExist + 6));
                    continue;
                }

                isExist = rowContentStr.indexOf("신고지연가산세 ");
                if (isExist == 0) {
                    // 신고지연가산세 0
                    bo.setDeclarationDelayWithAdditionalTaxCalculation(rowContentStr.substring(isExist + 8));
                    continue;
                }

                isExist = rowContentStr.indexOf("미신고가산세 ");
                if (isExist == 0) {
                    // 미신고가산세 0
                    bo.setUndeclaredPropertyTax(rowContentStr.substring(isExist + 7));
                    continue;
                }

                if (rowContentStr.contains(END_CODE)) {
                    // 63 총세액합계 12,040 67 담당자 이희진 68 접수일시 2024/01/25 14:56 69 수리일자 2024/01/29
                    //截取前缀
                    rowContentStr = rowContentStr.replaceFirst(END_CODE, "");
                    String[] contentSection = rowContentStr.split(BLANK);
                    if (contentSection.length > 0) {
                        bo.setTotalTaxAmount(contentSection[0]);
                    }
                    firstPage = false;
                }
            }
            // 取出 waybillNoSb 中 连续12位数字的字符串，出现多组，则逗号分割拼接为一个大字符串
            List<String> result = findContinuous12DigitSubstrings(bo.getBlawbNo(), waybillNoBO.getWaybillNoSb().toString());
            if (!result.isEmpty()) {
                bo.setWaybillNos(String.join(",", result));
            }
        }
        return bo;
    }

    /**
     * 读物流单号业务对象
     */
    public static class ReadWaybillNoBO {
        /**
         * 是否找到物流单号信息标识
         */
        private boolean findWayBillNoInfo;

        private StringBuilder waybillNoSb;

        public ReadWaybillNoBO(boolean findWayBillNoInfo, StringBuilder waybillNoSb) {
            this.findWayBillNoInfo = findWayBillNoInfo;
            this.waybillNoSb = waybillNoSb;
        }

        /**
         * 追加物流单号信息
         *
         * @param str str
         */
        public void appendWaybillNoSb(String str) {
            waybillNoSb.append(str);
        }

        public boolean getFindWayBillNoInfo() {
            return findWayBillNoInfo;
        }

        public void setFindWayBillNoInfo(boolean findWayBillNoInfo) {
            this.findWayBillNoInfo = findWayBillNoInfo;
        }

        public StringBuilder getWaybillNoSb() {
            return waybillNoSb;
        }

        public void setWaybillNoSb(StringBuilder waybillNoSb) {
            this.waybillNoSb = waybillNoSb;
        }
    }

    /**
     * 处理物流单号
     *
     * @param rowContentStr 行内容
     * @param bo            物流单号业务对象
     * @return 是否执行 continue true:执行；false：不执行
     */
    private static boolean processWaybillNo(String rowContentStr, ReadWaybillNoBO bo) {
        // 发现物流单号表头行
        if (!bo.getFindWayBillNoInfo() && rowContentStr.contains("33 모델ㆍ규격")) {
            bo.setFindWayBillNoInfo(true);
            return true;
        }
        // 发现物流单号结束行
        if (bo.getFindWayBillNoInfo() && rowContentStr.contains("38 세번부호")) {
            bo.setFindWayBillNoInfo(false);
        }
        // 有效的物流单号内容行，追加到 waybillNoSb 中
        if (bo.getFindWayBillNoInfo()) {
            bo.appendWaybillNoSb(rowContentStr);
//            logger.error("waybillNoSb： {}", bo.getWaybillNoSb());
            return true;
        }
        return false;
    }

    /**
     * 从字符串中提取连续出现的12位数字子字符串
     *
     * @param masterNo 主单号
     * @param input 输入字符串
     * @return 包含所有12位数字子字符串的列表
     */
    private static List<String> findContinuous12DigitSubstrings(String masterNo, String input) {
        logger.error("findContinuous12DigitSubstrings input： {}", input);
        if (StringUtils.isNotEmpty(input) && input.length() >= 12) {
            // 使用set，保证结果中的子字符串不重复
            Set<String> result = new LinkedHashSet<>();
            StringBuilder currentNumber = new StringBuilder();
            for (char c : input.toCharArray()) {
                // 如果是阿拉伯数字
                if (Character.isDigit(c)) {
                    currentNumber.append(c);
                    if (currentNumber.length() == 12) {
                        // 不等于主单号 并且 前缀不为 2025 才添加到结果中
                        if (!Objects.equals(masterNo, currentNumber.toString()) && !currentNumber.toString().startsWith("2025")) {
                            result.add(currentNumber.toString());
                            currentNumber.setLength(0);
                        } else {
                            // 清空当前数字串，继续寻找下一个12位数字子字符串
                            currentNumber.setLength(0);
                        }
                    }
                } else {
                    currentNumber.setLength(0);
                }
            }
            return new ArrayList<>(result);
        }
        return Collections.emptyList();
    }

    public static void main(String[] args) {
        String waybillNoSbString = "fsadfsad8sakldjgldfskhg3jkhgfds9009789788fklsjdf kgf fklsg nklfg;f ]pgfeqrg jlfj 123456789000123jfkgdh gfkjhlhgweghqer 8800098765432111gkjsd ekljrhgoiqerhg";

        List<String> result = findContinuous12DigitSubstrings("666", waybillNoSbString);
        System.out.println(String.join(",", result));
    }

}